<?php

namespace StudyBuddy\Controllers;

use \StudyBuddy\Request;
use \StudyBuddy\Responder;
use \StudyBuddy\String;
use \StudyBuddy\Validate;

/**
 * Class to process submittions from the
 * popup modal "quick registration"
 * This modal is used when someone joins via 3rd party auth like
 * via Twitter or FriendConnect and we need to collect email address
 * for that user.
 *
 * It also used for "Quick registration" where we ask for just email
 * and username (and sometimes captcha)
 *
 * This method only sends back ajax based response!
 *
 */
class Join extends Register
{

	//protected $requireToken = true;

	protected $permission = 'register_email';

	protected $aRequired = array('username', 'email');

	protected $userOK = true;


	/**
	 * Steps:
	 * Validate token,
	 *
	 * Must validate username
	 * Must validate email
	 * Sometimes validate captcha?
	 * Maybe here, maybe in sub-class
	 * Create all types of user records
	 * Create registration link,
	 * send registration email.
	 *
	 * On success send text to be shown to user
	 * OR if we need to redirect to newsletter signup
	 * then send back html for newsletter form modal
	 *
	 * On validation errors send back 'error' messages
	 * in ajax response
	 */
	public function main(){
		$this->checkUsername()
		->validateEmail()
		->createEmailRecord()
		->updateViewer();

		$this->oRegistry->Dispatcher->post($this->oRegistry->Viewer, 'onUserUpdate');
		$this->sendActivationEmail();
		$this->setReturn();
	}

	
	/**
	 * Update the viewer object
	 * with the new values
	 * then save the object
	 *
	 * @return object $this
	 */
	protected function updateViewer(){
		
		$currentRole = $this->oRegistry->Viewer->getRoleId();
		d('$currentRole: '.$currentRole);

		$this->pwd = String::makePasswd();

		$pwd = String::hashPassword($this->pwd);

		$this->oRegistry->Viewer->offsetSet('email', $this->email );

		/**
		 * Only change username IF this is a new registration
		 * and username was actually submitted
		 * 
		 * This means we don't allow to change username after
		 * the user has already joined the site.
		 * 
		 * This extra measure here will prevent a possible
		 * hack where an existing user otherwise may be able
		 * to change username
		 */
		if(!empty($this->oRequest['username']) ){
			$username = trim($this->oRequest['username']);
			$this->oRegistry->Viewer->offsetSet('username', $username);
			$this->oRegistry->Viewer->offsetSet('username_lc', strtolower($username) );
			/**
			 * Set the hashed password but it will only be
			 * set if this is a new registration (post-registration)
			 */
			$this->oRegistry->Viewer->offsetSet('pwd', $pwd);
		}


		/**
		 * Now sure about changing usergroup yet....
		 * This is not so easy because if we change to unactivated then
		 * user will not be able to do certain things like post comments
		 * but would have been able to do it if he decided NOT to provide
		 * email address and to just stay as 'external' account
		 *
		 * We have to do a more complicated check:
		 * If user isNewRegistration then we let such user to post comments
		 * and resources during the first visit otherwise we will check
		 * if user does not have email address -> ask to provide it
		 * if user is NOT activated then ask to activate it...
		 *
		 * OR we can just don't treat external account as trusted account
		 * until user provides email and activates it!
		 *
		 * I think the best way is to treat external account as trusted BUT
		 * periodically check and remind user to provide email address
		 * and to activate it...
		 *
		 */

		/**
		 * If current usergroup is external_users
		 * then we change it to unactivated_external
		 * otherwise change to unactivated
		 *
		 * unactivated_external have more rights that just
		 * unactivated but we can still spot that the user
		 * has not activated an account
		 * and present a reminder as some point.
		 */


//		$this->oRegistry->Viewer->offsetSet('role', 'unactivated_external');
		$this->oRegistry->Viewer->setRoleId('unactivated_external');
		$this->oRegistry->Viewer->save();

		/**
		 * 
		 * This is used in Register for sending out email
		 */
		$this->username = $this->oRegistry->Viewer->offsetGet('username');

		return $this;
	}


	/**
	 * For Ajax based submission
	 * send back Ajax object
	 * For regula form submission
	 * set the main element
	 *
	 * @todo When we have email newsletters collection form
	 * we will need to send action: modal
	 * and send html for that form!
	 *
	 */
	protected function setReturn(){
		$tpl = '
	<h1>Welcome to %s!</h1>
	<p class="larger">We have just emailed you 
	a temporary password and an account activation link</p>
	<p>Please make sure to follow instructions in that email and
	activate your new account</p>
	<p>We hope you will enjoy being a member of our site!</p>
	<br/>
	<p>
	<a class="regok" href="#" onClick="oSL.hideRegForm()">&lt;-- Return to site</a>&nbsp;
	<a class="regok" href="/settings/"> Edit profile --&gt;</a>
	</p> ';

		$ret = sprintf($tpl, $this->oRegistry->Ini->SITE_NAME);

		d('ret: '.$ret);

		if(Request::isAjax()){
			$a = array('action' => 'done', 'body' => $ret, 'uid' => $this->oRegistry->Viewer->getUid());

			Responder::sendJSON($a);
		}
	}


	/**
	 * @todo check that this username does not already
	 * exist
	 *
	 * @throws \StudyBuddy\FormException is username is invalid or already taken
	 *
	 * @return object $this
	 */
	protected function checkUsername(){
		if(empty($this->oRequest['username'])){

			return $this;
		}

		/**
		 * If user has not changed suggested username than
		 * we don't have to worry about validating it
		 */
		if($this->oRequest['username'] === $this->oRegistry->Viewer->username){

			return $this;
		}

		if(false === Validate::username($this->oRequest['username'])){

			throw new \StudyBuddy\FormException('Invalid username. Username can only contain English letters, numbers and a hyphen (but cannot start or end with the hyphen)', 'username');
		}

		$aReserved = \StudyBuddy\getReservedNames();

		$username = strtolower($this->oRequest['username']);
		$aUser = $this->oRegistry->Mongo->USERS->findOne(array('username_lc' => $username));

		if(!empty($aUser) || in_array( $username, $aReserved )){

			throw new \StudyBuddy\FormException('Someone else is already using this username. <br>
			Please choose a different username and resubmit the form', 'username');
		}

		/**
		 * Need to set $this->username because
		 * it's used in sendActivationEmail()
		 */
		$this->username = $this->oRequest['username'];

		return $this;
	}


	/**
	 * @todo
	 * Check that this email does not already exist
	 *
	 * @return object $this
	 */
	protected function validateEmail(){

		$email = strtolower($this->oRequest['email']);
		if(false === Validate::email( $email )){
			throw new \StudyBuddy\FormException('Email address '.$this->oRequest['email'].' is invalid<br/>Please correct it and resubmit the form', 'email');
		}

		$ret = $this->oRegistry->Mongo->EMAILS->findOne(array('email' => $email ));

		/**
		 * @todo when we have 'join existing account'
		 * form at the bottom then we can also suggest that user
		 * enters username/password to join this "twitter" account
		 * with an existing account
		 */
		if(!empty($ret)){
			throw new \StudyBuddy\FormException('<p>Someone else (probably you) is already registered with this email address
			<p/><p>If you forgot you password, <br/>please use the <a href="/remindpwd/">This link</a> to request a new password<br/>
			or use different email address to register a new account</p>', 'email');
		}

		/**
		 * Important to set $this->email
		 * it is used in parent class to createEmailRecord()
		 * as well as to email out the new registration password
		 */
		$this->email = $email;

		return $this;

	}

}
